/*
 * Copyright 2011-2013 OpenAjax Alliance
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

Components.utils.import("resource://oaa-accessibility-extension/cache-inspector-common.js");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");


/**
 * @file sidebar-rule-result-summary.js
 *
 * @desc Supports the sidebar showing rule summary information for a list if cache items 
 */

/* ---------------------------------------------------------------- */
/*            OAA_CI and OAA_AE_SIDEBAR.RuleResultView Object             */ 
/* ---------------------------------------------------------------- */

if (typeof OAA_CI === "undefined") {
  var OAA_CI = {};
}

if (typeof OAA_AE_SIDEBAR.RuleResultView === "undefined") {
  OAA_AE_SIDEBAR.RuleResultView = {};
}


/* ---------------------------------------------------------------- */
/*       Rule Category Cache Item Views and View Controllers        */ 
/* ---------------------------------------------------------------- */

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.init
 *
 * @desc Initializes the view
 */
 
OAA_AE_SIDEBAR.RuleResultView.init = function () {

};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.hide
 *
 * @desc Hides the element view controls
 */
 
OAA_AE_SIDEBAR.RuleResultView.hide = function () {

  var vbox_rule_result = window.document.getElementById('ID_VBOX_RULE_RESULT_VIEW');

  vbox_rule_result.hidden = true;
  
};


/**
 * @function OAA_AE_SIDEBAR.RuleResultView.show
 *
 * @desc Shows the element view controls
 */
 
OAA_AE_SIDEBAR.RuleResultView.show = function () {

  var vbox_rule_result = window.document.getElementById('ID_VBOX_RULE_RESULT_VIEW');

  vbox_rule_result.hidden = false;
  
};


/* ---------------------------------------------------------------- */
/*               Element Result View Functions                      */ 
/* ---------------------------------------------------------------- */

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.initStrings
 *
 * @desc Initializes message strings for view
 */
 
OAA_AE_SIDEBAR.RuleResultView.initStrings = function () {

  if (typeof this.MSG_SELECT_RULE !== 'string') {

    var nls_strings  = OAA_AE_SIDEBAR.nls_strings;

    if (!nls_strings) return;

    this.MSG_SELECT_RULE              = nls_strings.getString('selectRule');
    this.MSG_SELECT_RULE              = nls_strings.getString('selectRule');
    this.MSG_FILTERED_ITEM            = nls_strings.getString("filteredItem");
    this.MSG_FILTERED_ITEMS           = nls_strings.getString("filteredItems");
    this.MSG_NO_ELEMENT_RESULTS       = nls_strings.getString("noElementResults");
    this.MSG_ELEMENT                  = nls_strings.getString("element");
    this.MSG_INFORMATION              = nls_strings.getString("information");
    this.MSG_NO_ELEMENT_SELECTED      = nls_strings.getString("noElementSelected");
    this.MSG_MORE_INFORMATION_ELEMENT = nls_strings.getString("moreInformationElement");
    this.MSG_ELEMENT_RESULTS_FOR_RULE = nls_strings.getString("elementResultsForRule");
  }
};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.clear
 *
 * @desc Clears the node results from the tree
 */
 
OAA_AE_SIDEBAR.RuleResultView.clear = function () {

  this.initStrings();
  
//  OAA_AE_SIDEBAR.logger.debug("  Rule Result View Clear: Start " + this.MSG_SELECT_RULE);

  this.visible_tree_items = [];          
  
  var str_message = OAA_AE_SIDEBAR.RuleResultView.MSG_SELECT_RULE;
  
  var row = { level : 0,
              container : false,
              open : false,
            
              message : str_message,
              message_prop : 'message'
            };
  
  this.visible_tree_items.push(row);               

  this.elementButtonClear();  
  this.setView();
  
//  OAA_AE_SIDEBAR.logger.debug("  Rule Result View Clear: Remove Highlight ");

  OAA_AE_SIDEBAR.highlightRemove();

//  OAA_AE_SIDEBAR.logger.debug("  Rule Result View Clear: End ");

  this.node_results = [];
  this.node_result  = null;
    
};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.updateViewNameAndSummary
 *
 * @desc Updates the name of the view
 */
  
OAA_AE_SIDEBAR.RuleResultView.updateViewNameAndSummary = function () {

  var node_deck = window.document.getElementById('ID_DECK_VIEW');
  node_deck.selectedIndex = 1;
    
  var label_view = window.document.getElementById('ID_VIEW_NAME');  
  var msg = OAA_AE_SIDEBAR.RuleCategoryView.MSG_RULE + ": " + OAA_AE_SIDEBAR.RuleCategoryView.rule_result_item.rule_result.getRuleSummary();
  var tooltip_text = OAA_AE_SIDEBAR.RuleCategoryView.MSG_ELEMENT_RESULTS_FOR_RULE + ": " + OAA_AE_SIDEBAR.RuleCategoryView.rule_result_item.rule_result.getRuleSummary();
  label_view.setAttribute('value', msg);
  label_view.setAttribute('tooltiptext', tooltip_text);
   
  OAA_AE_SIDEBAR.setSummaryValues(OAA_AE_SIDEBAR.RuleResultView.summary_data);

};


/**
 * @function OAA_AE_SIDEBAR.RuleResultView.update
 *
 * @desc Shows the node results of a cache item
 *
 * @param {FilteredRuleResult}  filtered_rule_result  - filtered rule result object
 */
 
OAA_AE_SIDEBAR.RuleResultView.update = function (filtered_rule_result) {

  function getFilteredElementCount(count) {
    var str = "";
    
    if (count === 1) str = count + " " + OAA_AE_SIDEBAR.RuleResultView.MSG_FILTERED_ITEM;
    else str = count + " " + OAA_AE_SIDEBAR.RuleResultView.MSG_FILTERED_ITEMS;
         
    return str;
  }

  var SEVERITY = OpenAjax.a11y.SEVERITY;

  this.visible_tree_items = []; 
  
  this.node_results = [];
  this.node_result  = null;

  var tree           = window.document.getElementById('ID_TREE_RULE_RESULT_LIST');

  this.initStrings();

  OAA_AE_SIDEBAR.RuleResultView.filtered_rule_result = filtered_rule_result;
  OAA_AE_SIDEBAR.RuleResultView.summary_data = filtered_rule_result.getNodeResultSummary();

  OAA_AE_SIDEBAR.logger.debug("Rule Result View: "  + filtered_rule_result.getRuleSummary());

  OAA_AE_SIDEBAR.highlightRemove();

  if (filtered_rule_result.hasResults()) {
  
    var tree_view = new OpenAjax.a11y.formatters.TreeViewOfFilteredRuleResult(filtered_rule_result);
    
    OAA_AE_SIDEBAR.RuleResultView.tree_view = tree_view;

    if (typeof this.show_tree === 'boolean') this.showTree(this.show_tree);
    
    OAA_AE_SIDEBAR.RuleResultView.visible_tree_items = tree_view.getOpenNodeResults();

//    OAA_AE_SIDEBAR.logger.debug("  Node results tree view: " + tree_view.getOpenNodeResults().length);

    var IOM = OAA_AE_SIDEBAR.INFORMATION_OPTION;
    OAA_AE_SIDEBAR.setInformationMenuOption(IOM.CURRENT_SELECTION);

  } 
  else {    
  
    OAA_AE_SIDEBAR.RuleResultView.visible_tree_items = [];          

    var row = { level : 0,
                container : false,
                open : false,
            
                message : 'none',
                message_prop : 'message'
              };
  
    if (filtered_rule_result.node_results_filtered_out) row.message = getFilteredElementCount(filtered_rule_result.node_results_filtered_out)    
    else row.message = OAA_AE_SIDEBAR.RuleResultView.MSG_NO_ELEMENT_RESULTS;    

    OAA_AE_SIDEBAR.RuleResultView.visible_tree_items.push(row);               

  }  

  OAA_AE_SIDEBAR.RuleResultView.setView();

  OAA_AE_SIDEBAR.RuleResultView.elementButtonClear();
  
};


/**
 * @function OAA_AE_SIDEBAR.RuleResultView.setView
 *
 * @desc Shows the node results in a custom tree view
 */
 
OAA_AE_SIDEBAR.RuleResultView.setView = function () {

  var SEVERITY = OpenAjax.a11y.SEVERITY;

  var tree = window.document.getElementById('ID_TREE_RULE_RESULT_LIST');

  var visible_data = OAA_AE_SIDEBAR.RuleResultView.visible_tree_items;

//  OAA_AE_SIDEBAR.logger.debug("  Set view: " + visible_data.length);

  var treeView = {
    visibleData : visible_data,      
        
    selection   : null,
    treeBox     : null,
 
    isSeparator: function(row){ return false; },
    isSorted: function(){ return false; },
    getImageSrc: function(row,col){ return null; },        
    getRowProperties: function(row){ return ""; },

    setTree     : function(treeBox) { 
      this.treeBox = treeBox; 
    },
        
    get rowCount() { 
      return this.visibleData.length;
    },
        
    getCellText : function(row,column) {
      var item  = this.visibleData[row];

//      OAA_AE_SIDEBAR.logger.debug("  row: " + row + "  col: " + column + "  item: " + item);

      switch (column.id) {
       
      case "ID_TREECOL_ELEMENT":       
        if (typeof item.element === 'string') return item.element;
        if (typeof item.message  === 'string') return item.message;
        break;
       
      case "ID_TREECOL_ELEMENT_ORDER":
        if (typeof item.order   === 'number') return item.order.toString();
        break;

      case "ID_TREECOL_ELEMENT_RESULT":
        if (typeof item.result   === 'string') return item.result;      
        break;

      case "ID_TREECOL_ELEMENT_RESULT_MESSAGE":
        if (typeof item.result_message  === 'string') return item.result_message;
        break;
        
      default:
        break;
      }  

      return "";
    },
        
    isContainer: function(row) { 

      var item  = this.visibleData[row];
          
      if (typeof item.container === 'boolean') return item.container; 
        return false;           
    },
        
    isContainerEmpty: function(row){ 
      return false;           
    },
        
    isContainerOpen: function(row){ 
      var item  = this.visibleData[row];
          
      if (typeof item.open === 'boolean') return item.open; 

      return false;           
    },
    hasNextSibling: function(row, afterIndex) {
      var thisLevel = this.getLevel(row);
      for (var t = afterIndex + 1; t < this.visibleData.length; t++) {
        var nextLevel = this.getLevel(t);
        if (nextLevel == thisLevel) return true;
        if (nextLevel < thisLevel) break;
      }
      return false;     
    },  
    getParentIndex: function(row) {
        
      if (!this.isContainer(row)) {
        for (var t = row - 1; t >= 0 ; t--) {
          if (this.isContainer(t)) return t;
        }
      }
          
      return -1;
    },
        
    toggleOpenState: function(row){ 

      var item = this.visibleData[row];

      if (!item.container) return;

      if (item.open) {
        item.open = false;
 
        var thisLevel = this.getLevel(row);
        var deletecount = 0;
        for (var t = row + 1; t < this.visibleData.length; t++) {
          if (this.getLevel(t) > thisLevel) deletecount++;
          else break;
        }

        if (deletecount) {
          this.visibleData.splice(row + 1, deletecount);
          this.treeBox.rowCountChanged(row + 1, -deletecount);
        }
      }
      else {
        item.open = true;
      
        var prop_len = item.properties.length;

        for (var i = 0; i < prop_len; i++) {
          this.visibleData.splice(row + i + 1, 0, item.properties[i]);
        }
      
        this.treeBox.rowCountChanged(row + 1, prop_len);
      }
         
      this.treeBox.invalidateRow(row);
  
    },
       
    getLevel: function(row){ 
        
      var item  = this.visibleData[row];
          
      if (typeof item.level === 'number') return item.level; 
          
      return 0; 
    },
        
    getCellProperties: function(row,column) {

      var item  = this.visibleData[row];
      var property_value = "";

      switch (column.id) {

      case "ID_TREECOL_ELEMENT":       
        if (typeof item.element_prop === 'string') property_value = item.element_prop;
        if (typeof item.message_prop === 'string') property_value = item.message_prop;
        break;
       
      case "ID_TREECOL_ELEMENT_ORDER":
        if (typeof item.order_prop  === 'string')  property_value = item.order_prop;
        break;

      case "ID_TREECOL_ELEMENT_RESULT":
        if (typeof item.result_prop  === 'string')  property_value = item.result_prop;
        break;
       
      case "ID_TREECOL_ELEMENT_RESULT_MESSAGE":
        if (typeof item.result_message_prop  === 'string')  property_value = item.result_message_prop;
        break;
       

      default:
        break;
      }  

      return property_value;

    },
        
    getColumnProperties: function(colid,col) { return ""; }
 };
      
  tree.view = treeView;

};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.sortNodeResultList
 *
 * @desc Sorts the list of rules by a sort property
 */
 
OAA_AE_SIDEBAR.RuleResultView.sortNodeResultList = function (column) {

//  OAA_AE_SIDEBAR.logger.debug("Sort Node Result List: " + column.id);

  var tree = window.document.getElementById('ID_TREE_RULE_RESULT_LIST');

  var tree_view = OAA_AE_SIDEBAR.RuleResultView.tree_view;
  
  if (!tree_view) return;

  var column_name;
  var order = tree.getAttribute("sortDirection") == "ascending" ? 1 : -1;
  
  //if the column is passed and it's already sorted by that column, reverse sort
  if (column) {
    column_name = column.id;

    if (tree.getAttribute("sortResource") == column_name) {
      order *= -1;
    }
  } else {
    column_name = tree.getAttribute("sortResource");
  }

  //setting these will make the sort option persist
  tree.setAttribute("sortDirection", order == 1 ? "ascending" : "descending");
  tree.setAttribute("sortResource", column_name);
  
  //set the appropriate attributes to show to indicator
  var cols = tree.getElementsByTagName("treecol");

  for (var i = 0; i < cols.length; i++) {
    cols[i].removeAttribute("sortDirection");
  }

  document.getElementById(column_name).setAttribute("sortDirection", order == 1 ? "ascending" : "descending");


  switch (column.id) {
       
  case "ID_TREECOL_ELEMENT":
    tree_view.sortListOfNodeResults('element', order);
    break;
       
  case "ID_TREECOL_ELEMENT_ORDER":       
    tree_view.sortListOfNodeResults('order', order);
    break;

  case "ID_TREECOL_ELEMENT_RESULT":       
    tree_view.sortListOfNodeResults('severity', order);
    break;

  case "ID_TREECOL_ELEMENT_RESULT_MESSAGE":       
    tree_view.sortListOfNodeResults('result_message', order);
    break;
              


  default:
    break;
  }  

  OAA_AE_SIDEBAR.RuleResultView.visible_tree_items = tree_view.getOpenNodeResults();

  OAA_AE_SIDEBAR.RuleResultView.setView();

};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.setTreeControls
 *
 * @desc Disables or enables tree collapse and expand buttons
 *
 * @param {Boolean}   flag   - If true to enable and false to disable
 */
 
OAA_AE_SIDEBAR.RuleResultView.setTreeControls = function(flag) {

  var button_expand = window.document.getElementById('ID_BUTTON_RULE_RESULT_EXPAND_TREE');
  if (flag) button_expand.setAttribute('disabled', 'false');
  else button_expand.setAttribute('disabled', 'true');

  var button_collapse = window.document.getElementById('ID_BUTTON_RULE_RESULT_COLLAPSE_TREE');
  if (flag) button_collapse.setAttribute('disabled', 'false');
  else button_collapse.setAttribute('disabled', 'true');

};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.showTree
 *
 * @desc Expands or contracts showing the properties of a node result in a tree view 
 *
 * @param {Boolean}   flag   - If true expand tree to show all properties, if false collapse tree to hide properties
 */
 
OAA_AE_SIDEBAR.RuleResultView.showTree = function(flag) {

  var tree_view = OAA_AE_SIDEBAR.RuleResultView.tree_view;
  
  if (!tree_view) return;

  tree_view.setOpenState(flag);

//    OAA_AE_SIDEBAR.logger.debug("  Flag: " + flag);

    // Update the columns displayed
  
  OAA_AE_SIDEBAR.RuleResultView.visible_tree_items = tree_view.getOpenNodeResults();
  
  OAA_AE_SIDEBAR.RuleResultView.setView();    
   
  OAA_AE_SIDEBAR.RuleResultView.show_tree = flag;

};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.nodeResultListOnSelect
 *
 * @desc Updates cache item information button when a cache item is selected
 */
 
OAA_AE_SIDEBAR.RuleResultView.onSelect = function () {

  var IOM = OAA_AE_SIDEBAR.INFORMATION_OPTION;

  var tree = window.document.getElementById('ID_TREE_RULE_RESULT_LIST');

  if (!tree) return;

  var index = tree.currentIndex;
    
  if (index < 0) return;
 
  var visible_tree_item = OAA_AE_SIDEBAR.RuleResultView.visible_tree_items[index];
  var node_result       = visible_tree_item.node_result;
 
  if (typeof node_result != 'object') {
    OAA_AE_SIDEBAR.RuleResultView.node_result    = null;
    OAA_AE_SIDEBAR.RuleResultView.elementButtonClear(); 
    OAA_AE_SIDEBAR.highlightRemove();
  }
  else {    
    OAA_AE_SIDEBAR.RuleResultView.node_result    = node_result;
    OAA_AE_SIDEBAR.RuleResultView.elementButtonUpdate(node_result.getOrdinalPosition(), node_result);   
    OAA_AE_SIDEBAR.showNodeResultInformation(node_result);
    OAA_AE_SIDEBAR.highlightNodeResults(node_result);
    OAA_AE_SIDEBAR.setInformationMenuOption(IOM.CURRENT_SELECTION);
  }   
};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.showNodeResultInformation
 *
 * @desc Show information about the currently selected element 
 */
 
OAA_AE_SIDEBAR.RuleResultView.showNodeResultInformation = function () {

  if (this.node_result) {
    OAA_AE_SIDEBAR.showRulePropertiesDialog(this.node_result);
  }  

};

/* ---------------------------------------------------------------- */
/*                 element Information Button                       */ 
/* ---------------------------------------------------------------- */

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.elementButtonClear
 *
 * @desc Clears the rules in the rules tabs
 */
 
OAA_AE_SIDEBAR.RuleResultView.elementButtonClear = function () {

  var button_element_info = window.document.getElementById('ID_BUTTON_ELEMENT_RESULT_VIEW_SHOW_ELEMENT');

  if (button_element_info) {
    button_element_info.setAttribute("label", OAA_AE_SIDEBAR.RuleResultView.MSG_ELEMENT + ' ' + OAA_AE_SIDEBAR.RuleResultView.MSG_INFORMATION);
    button_element_info.setAttribute('tooltiptext', OAA_AE_SIDEBAR.RuleResultView.MSG_NO_ELEMENT_SELECTED);
    button_element_info.setAttribute("disabled",    "true");
  }
  
  if (OAA_AE_SIDEBAR.cache_item_properties_dialog && 
      OAA_AE_SIDEBAR.cache_item_properties_dialog.cache_item_properties) {
    OAA_AE_SIDEBAR.cache_item_properties_dialog.cache_item_properties.clear();
  }

  this.node_result = null;

};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.elementButtonUpdate
 *
 * @desc Updates the label of the show rule information button
 *
 * @param {Number}      element_number  - position of a element item in a list
 * @param {NodeResult}  node_result     - Node result object    
 */
 
OAA_AE_SIDEBAR.RuleResultView.elementButtonUpdate = function (element_number, node_result) {

  var button_element_info = window.document.getElementById('ID_BUTTON_ELEMENT_RESULT_VIEW_SHOW_ELEMENT');

  var label;

  if (button_element_info) {
  
    OAA_AE_SIDEBAR.RuleResultView.node_result = node_result;
    
    if (node_result.getRuleSummary && node_result.cache_item) {
    
      label =  OAA_AE_SIDEBAR.RuleResultView.MSG_MORE_INFORMATION_ELEMENT + ": " + node_result.getRuleSummary();

      button_element_info.setAttribute("label", OAA_AE_SIDEBAR.RuleResultView.MSG_ELEMENT + ' ' + element_number + ' ' + OAA_AE_SIDEBAR.RuleResultView.MSG_INFORMATION);
      button_element_info.setAttribute("tooltiptext",  label);
      button_element_info.setAttribute("disabled", "false");

      if (OAA_AE_SIDEBAR.cache_item_properties_dialog && 
          OAA_AE_SIDEBAR.cache_item_properties_dialog.cache_item_properties) {
        OAA_AE_SIDEBAR.cache_item_properties_dialog.cache_item_properties.update(node_result.cache_item);
      }

      OAA_AE_SIDEBAR.highlightNodeResults(node_result);

    }
    else {

      label = OAA_AE_SIDEBAR.RuleResultView.MSG_NO_ELEMENT_SELECTED;

      button_element_info.setAttribute("label", OAA_AE_SIDEBAR.RuleResultView.MSG_ELEMENT + ' ' + OAA_AE_SIDEBAR.RuleResultView.MSG_INFORMATION);
      button_element_info.setAttribute("tooltiptext",  label);
      button_element_info.setAttribute("disabled", "true");
      
      if (OAA_AE_SIDEBAR.cache_item_properties_dialog && 
          OAA_AE_SIDEBAR.cache_item_properties_dialog.cache_item_properties) {
        OAA_AE_SIDEBAR.cache_item_properties_dialog.cache_item_properties.clear();
      }

    } 
  }  
};

/**
 * @function OAA_AE_SIDEBAR.RuleResultView.showElementDetails
 *
 * @desc Show information about the currently selected element 
 */
 
OAA_AE_SIDEBAR.RuleResultView.showElementDetails = function () {

//  OAA_AE_SIDEBAR.logger.debug("Node Result Information: " + OAA_AE_SIDEBAR.RuleResultView.node_result);

  var node_result = OAA_AE_SIDEBAR.RuleResultView.node_result;

  if (node_result) {
  
    var cache_item = node_result.cache_item;
  
    if (cache_item && 
        (!OAA_AE_SIDEBAR.cache_item_properties_dialog || 
         !OAA_AE_SIDEBAR.cache_item_properties_dialog.cache_item_properties)) {
      OAA_AE_SIDEBAR.showCacheItemPropertiesDialog(cache_item);
    }
  } 

};
